package com.candy.biz.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ObjectUtil;
import com.candy.biz.domain.dto.SysUserDTO;
import com.candy.biz.domain.entity.SysMenu;
import com.candy.biz.domain.param.SysMenuQueryParam;
import com.candy.biz.domain.param.SysMenuSaveParam;
import com.candy.biz.domain.vo.SysMenuVO;
import com.candy.biz.manager.SysMenuManager;
import com.candy.biz.manager.SysUserManager;
import com.candy.biz.mapper.SysMenuMapper;
import com.candy.biz.service.SysMenuService;
import com.candy.common.constant.CommonConstant;
import com.candy.common.domain.PageVO;
import com.candy.common.utils.CommonUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.If;
import com.mybatisflex.core.query.QueryOrderBy;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

import static com.candy.biz.domain.entity.table.SysMenuTableDef.SYS_MENU;
import static com.candy.biz.domain.entity.table.SysRoleMenuTableDef.SYS_ROLE_MENU;
import static com.candy.biz.domain.entity.table.SysUserRoleTableDef.SYS_USER_ROLE;


/**
 * 菜单权限-服务层实现。
 *
 * @author rong xi
 * @date 2023/10/07 15:28
 * @version 1.0.0
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    /**
     * 查询菜单权限详情
     *
     * @param id 菜单权限id
     * @return 详情VO
     */
    @Override
    public SysMenuVO queryInfo(Long id) {
        return this.getByIdOpt(id).map(SysMenuManager::poToVo).orElse(null);
    }

    /**
     * 分页查询菜单权限
     *
     * @param param 查询参数
     * @return 分页结果
     */
    @Override
    public PageVO<SysMenuVO> queryPage(SysMenuQueryParam param) {
        Page<SysMenu> page = queryChain()
                .select(SYS_MENU.ALL_COLUMNS)
                .from(SYS_MENU)
                .where(SYS_MENU.ID.eq(param.getId(), If::notNull))
                .and(SYS_MENU.ID.eq(param.getId(), If::notNull))
                .and(SYS_MENU.MENU_NAME.like(param.getMenuName(), If::hasText))
                .and(SYS_MENU.TYPE.eq(param.getType(), If::notNull))
                .and(SYS_MENU.REMARK.eq(param.getRemark(), If::hasText))
                .orderBy(param.getOrderBy(SYS_MENU))
                .page(param.getPage());
        return SysMenuManager.pageToPageVO(page);
    }


    /**
     * 根据条件查询菜单权限树集合。
     *
     * @param param 查询参数
     * @return 查询结果
     */
    @Override
    public List<Tree<Long>> queryTreeList(SysMenuQueryParam param){
        List<SysMenu> list = queryChain()
                .select(SYS_MENU.ALL_COLUMNS)
                .from(SYS_MENU)
                .where(SYS_MENU.ID.eq(param.getId(), If::notNull))
                .and(SYS_MENU.ID.eq(param.getId(), If::notNull))
                .and(SYS_MENU.MENU_NAME.like(param.getMenuName(), If::hasText))
                .and(SYS_MENU.TYPE.eq(param.getType(), If::notNull))
                .orderBy(param.getOrderBy(SYS_MENU))
                .list();
        return SysMenuManager.posToTreeList(list);
    }

    /**
     * 根据条件查询菜单权限树。
     *
     * @param param 查询参数
     * @return 查询结果
     */
    @Override
    public Tree<Long> queryTree(SysMenuQueryParam param){
        List<SysMenu> list = queryChain()
                .select(SYS_MENU.ALL_COLUMNS)
                .from(SYS_MENU)
                .where(SYS_MENU.ID.eq(param.getId(), If::notNull))
                .and(SYS_MENU.ID.eq(param.getId(), If::notNull))
                .and(SYS_MENU.MENU_NAME.like(param.getMenuName(), If::hasText))
                .and(SYS_MENU.TYPE.eq(param.getType(), If::notNull))
                .and(SYS_MENU.REMARK.eq(param.getRemark(), If::hasText))
                .orderBy(param.getOrderBy(SYS_MENU))
                .list();
        return SysMenuManager.posToTree(list);
    }

    /**
     * 根据查询条件导出菜单权限。
     *
     * @param param 查询条件
     */
    @Override
    @SneakyThrows
    public void export(SysMenuQueryParam param) {
        //修改分页条件
        param.preparationExport();
        //查询数据
        List<SysMenuVO> rows = queryPage(param).getList();
        //导出文件
        CommonUtil.exportExcel("菜单权限",rows,SysMenuVO.class);
    }


    /**
     * 保存菜单权限
     *
     * @param param 保存参数
     * @return 保存结果
     */
    @Override
    public Boolean saveHandle(SysMenuSaveParam param) {
        return CommonUtil.<SysMenuSaveParam,Boolean>predicateFunction(param,
                (p)-> ObjectUtil.isNull(p.getId()),
                (p)->this.save(SysMenuManager.insertPrepare(p)),
                (p)-> this.updateById(SysMenuManager.updatePrepare(p)));
    }

    /**
     * 查询用户菜单列集合
     * @param userId 用户id
     * @return 菜单集合
     */
    @Override
    public List<Tree<String>> queryMenus(Long userId) {

        SysUserDTO userInfo = SysUserManager.getUserInfo(userId);
        List<SysMenu> list;
        //超管查询全部
        if(userInfo.getType().equals(CommonConstant.ZERO)){
            //查询所有菜单权限
            list = queryChain()
                    .select(SYS_MENU.ALL_COLUMNS)
                    .from(SYS_MENU)
                    .where(SYS_MENU.TYPE.eq(CommonConstant.ONE))
                    .orderBy(new QueryOrderBy(SYS_MENU.ORDER_NUM, CommonConstant.ORDER_ASC))
                    .list();
        } else {
            list = queryChain()
                    .select(SYS_MENU.ALL_COLUMNS)
                    .from(SYS_MENU)
                    .innerJoin(SYS_ROLE_MENU)
                    .on(SYS_ROLE_MENU.MENU_ID.eq(SYS_MENU.ID))
                    .innerJoin(SYS_USER_ROLE)
                    .on(SYS_USER_ROLE.ROLE_ID.eq(SYS_ROLE_MENU.ROLE_ID))
                    .where(SYS_USER_ROLE.USER_ID.eq(userId))
                    .and(SYS_MENU.TYPE.eq(CommonConstant.ONE))
                    .orderBy(new QueryOrderBy(SYS_MENU.ORDER_NUM, CommonConstant.ORDER_ASC))
                    .list();
        }
        return SysMenuManager.posToMenuList(list);
    }

    /**
     * 查询用户权限集合。
     * @param userId 用户id
     * @return 权限集合
     */
    @Override
    public List<String> queryPermissions(Long userId) {

        SysUserDTO userInfo = SysUserManager.getUserInfo(userId);
        List<String> list;
        //超管查询全部
        if(userInfo.getType().equals(CommonConstant.ZERO)){
            list = queryChain()
                    .select(SYS_MENU.ALL_COLUMNS)
                    .from(SYS_MENU)
                    .where(SYS_MENU.TYPE.eq(CommonConstant.TWO))
                    .orderBy(new QueryOrderBy(SYS_MENU.ORDER_NUM, CommonConstant.ORDER_ASC))
                    .list().stream().map(SysMenu::getPermissionCode).distinct().collect(Collectors.toList());
        }else{
            list = queryChain()
                    .select(SYS_MENU.ALL_COLUMNS)
                    .from(SYS_MENU)
                    .innerJoin(SYS_ROLE_MENU)
                    .on(SYS_ROLE_MENU.MENU_ID.eq(SYS_MENU.ID))
                    .innerJoin(SYS_USER_ROLE)
                    .on(SYS_USER_ROLE.ROLE_ID.eq(SYS_ROLE_MENU.ROLE_ID))
                    .where(SYS_USER_ROLE.USER_ID.eq(userId))
                    .and(SYS_MENU.TYPE.eq(CommonConstant.TWO))
                    .orderBy(new QueryOrderBy(SYS_MENU.ORDER_NUM, CommonConstant.ORDER_ASC))
                    .list().stream().map(SysMenu::getPermissionCode).distinct().collect(Collectors.toList());
        }
        return list;
    }
}
